package com.jl.basicframework.httpservice;

import android.util.Log;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.jl.basicframework.model.bean.HttpBean;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.concurrent.TimeUnit;

import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Converter;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

/***
 * @author 作者:姜澜
 * 时间:2022/3/8
 * 邮箱:316879104@pp.com
 * 类简述: Retrofit 请求工具
 */
public class RetrofitUtils {

    /**
     * 日志标识
     */
    private final static String TAG = "IRetrofitUtils";

    /**
     * 工具单例对象
     */
    private static RetrofitUtils iRetrofitUtils;
    /**
     * Retrofit 对象
     */
    private Retrofit retrofit;

    private final Retrofit.Builder retrofitBuilder;
    private final OkHttpClient.Builder okHttpBuilder;

    /**
     * 连接超时
     */
    private int connectTimeout = 35;
    /**
     * 读取超时
     */
    private int readTimeout = 35;
    /**
     * 写入超时
     */
    private int writeTimeout = 35;


    /**
     * 私有化构造函数
     */
    private RetrofitUtils(){
        retrofitBuilder = new Retrofit.Builder();
        okHttpBuilder = new OkHttpClient()
                .newBuilder();
    }

    /**
     * 获取单例对象
     * @return RetrofitUtils单例对象
     */
    public static RetrofitUtils getInstances() {
        if (iRetrofitUtils == null) {
            synchronized (RetrofitUtils.class) {
                if (iRetrofitUtils == null) {
                    iRetrofitUtils = new RetrofitUtils();
                }
            }
        }
        return iRetrofitUtils;
    }

    /**
     * 初始化工具
     * @return
     */
    public RetrofitUtils initUtils(){
        OkHttpClient okHttpClient = okHttpBuilder
                .writeTimeout(writeTimeout, TimeUnit.SECONDS)
                .readTimeout(readTimeout, TimeUnit.SECONDS)
                .connectTimeout(connectTimeout, TimeUnit.SECONDS)
                .build();


        retrofit = retrofitBuilder
                //GSON解析器
                .addConverterFactory(GsonConverterFactory
                        .create(new GsonBuilder()
                        .setLenient()
                        .create()))
                .client(okHttpClient)
                .build();

        return this;
    }

    /**
     * 创建请求API
     */
    public <T> T createAPI(Class<T> clazz) {

        return retrofit.create(clazz);
    }

    /**
     * 网络回调监听
     * @param <C>
     */
    public interface IHttpReplyListener<C> {
        /**
         * 网络回复回调
         * @param object
         */
        void onReply(C object);

        /**
         * 错误信息
         * @param message
         */
        void onError(String message);
    }

    /**
     * 设置连接超时时间
     * @param connectTimeout
     */
    public RetrofitUtils setConnectTimeout(int connectTimeout) {
        this.connectTimeout = connectTimeout;
        return this;
    }

    /**
     * 设置读取超时时间
     * @param readTimeout
     */
    public RetrofitUtils setReadTimeout(int readTimeout) {
        this.readTimeout = readTimeout;
        return this;
    }

    /**
     * 设置写入超时时间
     * @param writeTimeout
     */
    public RetrofitUtils setWriteTimeout(int writeTimeout) {
        this.writeTimeout = writeTimeout;
        return this;
    }

    /**
     * 服务器地址
     * @param url 地址
     */
    public RetrofitUtils setUrl(String url) {
        retrofitBuilder.baseUrl(url);
        return this;
    }

    /**
     * 添加拦截器
     */
    public RetrofitUtils addInterceptor(Interceptor interceptor){
        okHttpBuilder.addInterceptor(interceptor);
        return this;
    }

    /**
     * 访问服务器
     * @param call 访问参数
     * @param iHttpReplyListener 访问回调监听
     * @param <C> 服务器返回参数
     * @return
     */
    public <C> C enqueue(ICall<C> call, final IHttpReplyListener<C> iHttpReplyListener){

        call.enqueue(new Callback<HttpBean<C>>() {
            @Override
            public void onResponse(Call<HttpBean<C>> call, Response<HttpBean<C>> response) {

                //获取响应参数
                HttpBean<C> replyData = response.body();

                //网络访问成功回调
                switch (HttpCodeEnum.parse(replyData.getCode())){
                    case SUCCESS:
                        //成功响应
                        iHttpReplyListener.onReply(replyData.getData());
                        break;

                    default:
                        //失败响应
                        Log.e(TAG,replyData.toString());
                        iHttpReplyListener.onError(replyData.getMsg());
                        break;
                }
            }

            @Override
            public void onFailure(Call<HttpBean<C>> call, Throwable t) {
                //网络访问错误回调
                Log.e(TAG,t.getMessage());
                iHttpReplyListener.onError("网络错误");
            }
        });

        return null;
    }

    /**
     * 网络代码枚举
     */
    enum HttpCodeEnum{
        /**
         * 访问成功
         */
        SUCCESS(0,"成功"),
        /**
         * 未知响应
         */
        UNKNOWN(-101,"未知响应code")
        ;

        /**
         * 网络代码
         */
        private final int code;
        /**
         * 说明
         */
        private final String message;

        HttpCodeEnum(int code, String message) {
            this.code = code;
            this.message = message;
        }

        public int getCode() {
            return code;
        }

        public String getMessage() {
            return message;
        }

        /**
         * 解析对应code码
         * @param code
         * @return
         */
        public static String parseMessage(int code){

            HttpCodeEnum[] httpCodeEnums = HttpCodeEnum.values();
            for (HttpCodeEnum codeEnum : httpCodeEnums){
                if (codeEnum.getCode() == code){
                    return codeEnum.getMessage();
                }
            }

            return "未知状态";
        }

        /**
         * 解析对应code码
         * @param code
         * @return
         */
        public static HttpCodeEnum parse(int code){

            HttpCodeEnum[] httpCodeEnums = HttpCodeEnum.values();
            for (HttpCodeEnum codeEnum : httpCodeEnums){
                if (codeEnum.getCode() == code){
                    return codeEnum;
                }
            }

            return UNKNOWN;
        }
    }
}
